package org.hxyjs.aop;


import org.hxyjs.dto.DTO;
import org.hxyjs.log.CustomLogger;
import org.hxyjs.log.Log;
import org.hxyjs.rabbitmq.RabbitUtil;
import org.hxyjs.vo.MailUser;
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * LG
 */
@Component
@Aspect
public class MailAspect {

	@Resource
    DirectExchange exchange;
	@Resource
	RabbitUtil rabbitUtil;


	//logg4j工具类
	public static Logger logger = Logger.getLogger(MailAspect.class);
	//自定义级别工具类
	Logger customLogger = CustomLogger.getInstance().createLogger("d:/log/mail/", "controller", "--->", false);

	// 获取开始时间
	private long BEGIN_TIME;

	// 获取结束时间
	private long END_TIME;

	// 定义本次log实体
	private Log log = new Log();

	@Pointcut("execution(* org.hxyjs.controller..*.*(..))")
	private void controllerAspect() {
	}

	/**
	 * 方法开始执行
	 */
	@Before("controllerAspect()")
	public void doBefore() {
		BEGIN_TIME = new Date().getTime();
		System.out.println("service开始");
	}

	/**
	 * 方法结束执行
	 */
	@After("controllerAspect()")
	public void after() {
		END_TIME = new Date().getTime();
		System.out.println("service结束");
	}

	/**
	 * 方法结束执行后的操作
	 */
	@AfterReturning("controllerAspect()")
	public void doAfter() {

		if (log.getState() == 1 || log.getState() == -1) {
			log.setActionTime(END_TIME - BEGIN_TIME);
			log.setGmtCreate(new Date(BEGIN_TIME));
			System.out.println("service返回");
			//System.out.println(">>>>>>>>>>存入到数据库");
		} else {
			//System.out.println(log);
			//System.out.println(">>>>>>>>不存入到数据库");
		}
	}

	/**
	 * 方法有异常时的操作
	 */
	@AfterThrowing("controllerAspect()")
	public void doAfterThrow() {
		System.out.println("例外通知-----------------------------------");
	}

	/**
	 * 方法执行
	 * 
	 * @param pjp
	 * @return
	 * @throws Throwable
	 */
	@Around("controllerAspect()")
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		// 日志实体对象
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();


		// 拦截的实体类，就是当前正在执行的controller
		Object target = pjp.getTarget();
		// 拦截的方法名称。当前正在执行的方法
		String methodName = pjp.getSignature().getName();
		System.out.println(methodName);
		// 拦截的方法参数
		Object[] args = pjp.getArgs();
		// 拦截的放参数类型
		Signature sig = pjp.getSignature();
		MethodSignature msig = null;
		if (!(sig instanceof MethodSignature)) {
			throw new IllegalArgumentException("该注解只能用于方法");
		}
		msig = (MethodSignature) sig;
		Class[] parameterTypes = msig.getMethod().getParameterTypes();

		DTO<MailUser> dto = null;

		Method method = null;
		try {
			System.out.println(target.getClass().getName());
			method = target.getClass().getMethod(methodName, parameterTypes);
		} catch (NoSuchMethodException e1) {
			// TODO Auto-generated catch block
			//e1.printStackTrace();
		} catch (SecurityException e1) {
			// TODO Auto-generated catch block
			//e1.printStackTrace();
		}

		if (null != method) {
			// 判断是否包含自定义的注解，说明一下这里的SystemLog就是我自己自定义的注解
			if (method.isAnnotationPresent(SystemMail.class)) {
				SystemMail systemMail = method.getAnnotation(SystemMail.class);
				log.setModule(systemMail.module());
				log.setMethod(systemMail.methods());
				log.setLoginIp(getIp(request));
				log.setActionUrl(request.getRequestURI());
				log.setActionTime(new Date().getTime());

				String op = systemMail.op();
				String queueName = systemMail.queueName();//要发送的队列名

				try {
					dto =  (DTO)pjp.proceed();
					MailUser mailUser = dto.getT();//通过拦截方法运行完成的返回值中得到的用户信息来发邮件
					sendMail(mailUser,op,queueName);
					log.setDescription("执行成功");
					System.out.println("执行成功");
					logger.info(log.printfomat());
					CustomLogger.getInstance().customLog(customLogger,log.printfomat());
					log.setState((short) 1);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					log.setDescription("执行失败");
					log.setState((short) -1);
					e.printStackTrace();
				}
			} else {// 没有包含注解
				Object object =  pjp.proceed();
				System.out.println(object);
				dto = (DTO)object;
				log.setDescription("此操作不包含邮件注解");
				System.out.println("service此操作不包含邮件注解");
				log.setState((short) 0);
			}
		} else { // 不需要拦截直接执行
			dto =  (DTO)pjp.proceed();
			System.out.println("service不需要拦截直接执行");
			log.setDescription("不需要拦截直接执行");
			log.setState((short) 0);
		}
		return dto;
	}

	/**
	 * 获取ip地址
	 * 
	 * @param request
	 * @return
	 */
	private String getIp(HttpServletRequest request) {
		if (request.getHeader("x-forwarded-for") == null) {
			return request.getRemoteAddr();
		}
		return request.getHeader("x-forwarded-for");
	}


	/**
	 * 发送邮件部分
	 */
	public void   sendMail(MailUser mailUser,String op,String queueName){
		//使用自定义的rabbitUtils工具类（封装了rabbitTemplate操作友谊 member被转成了json字符串）
		mailUser.setOp(op);
		rabbitUtil.sendToQueue(exchange, queueName, mailUser);
	}
}